use std::{net::SocketAddr, str::FromStr};
use tokio::io::AsyncReadExt;
use tweeny_rpc::{
    client::with_default_serder_tcp, macros::rpc_service, utils::helper_types::StaticBytes,
};

#[rpc_service(client, static_ref_all_under_surface_solve(req))]
trait CoolServ {
    async fn proc1(&self, bytes: StaticBytes) -> usize;
}

#[tokio::main]
async fn main() -> std::io::Result<()> {
    env_logger::init();

    let addr = SocketAddr::from_str("127.0.0.1:22330").unwrap();
    let (serv, handle) = with_default_serder_tcp(addr).await?;

    tokio::spawn(serv);
    let handle = CoolServReqHandle(handle);

    let mut f =
        tokio::fs::File::open("/mnt/Data/Akira.1988.1080p.Bluray.AV1.Opus.Multi4-dAV1nci.mkv")
            .await?;
    const BUF_SIZE: usize = 100 * 1024 * 1024;
    let mut buf = Box::new([0u8; BUF_SIZE]);
    let mut n = f.read(&mut *buf).await?;
    while n > 0 {
        let leaked: &'static mut [u8; BUF_SIZE] = Box::leak(buf);
        let raw_ptr = leaked as *mut _;
        let res = handle.proc1(StaticBytes(&leaked[..n]), None).await;
        println!("{res:?}");

        // SAFETY: the input to our rpc call is only read when serializing,
        // dropped when the serialization is done, so:
        // 0. the ptr isn't dangling since it's leaked from a Box
        // 1. the content is as valid as before the leak
        // 2. by the time the rpc call returns, no one else is holding the ptr
        buf = unsafe { Box::from_raw(raw_ptr) };
        n = f.read(&mut *buf).await?;
    }

    Ok(())
}
